package com.sparrow.utils;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;

import com.sparrow.constant.FILE;
import com.sparrow.constant.REGEX;

public class ImageUtil {
	/**
	 * JAVA等比缩放函数
	 * 
	 * @author zhanglizhi
	 * @date Jun 19, 2011
	 * @version 1.0
	 * @param srcImagePath原图路径
	 * @param descImagePath缩放后路径
	 * @param width缩放后宽度
	 * @param height缩放后高度
	 *            -1则只按宽度比例进行缩放
	 * @param waterImagePath水印图位置
	 * @param fillWhite
	 *            不足是否需要补白
	 * @throws IOException
	 */
	public static void makeThumbnail(String srcImagePath, String descImagePath,
			int width, int height, String waterImagePath, boolean fillWhite)
			throws IOException {
		// 目标图扩展名
		String extension = srcImagePath
				.substring(srcImagePath.lastIndexOf('.') + 1);
		// 如果为gif图则直接保存
		if (extension.toLowerCase().equals("gif")
				&& descImagePath.contains(FILE.SIZE.BIG)) {
			FileUtil.getInstance().copy(srcImagePath,descImagePath);
			return;
		} else {
			// 源图文件对象
			File srcFile = new File(srcImagePath);
			// 目录图所在路径
			String descDirectoryPath = descImagePath.substring(0, descImagePath
					.lastIndexOf('/') + 1);
			// 判断并创建原图路径
			File descDirectory = new File(descDirectoryPath);
			if (!descDirectory.exists()) {
				descDirectory.mkdirs();
			}
			// 目标图文件对象
			File descFile = new File(descImagePath);
			// 原图缓存区
			BufferedImage srcImage = ImageIO.read(new FileInputStream(srcFile));
			// 目标图宽度
			int descWidth = width;
			// 目标图高度
			int descHeight = height;
			// 缩放比例
			double scale = 1;
			// 剪切后的目标图
			BufferedImage descImage = null;
			// 是否需要缩放
			boolean isThumbnail = true;
			// 剪切x轴位置
			int x = 0;
			// 剪切Y轴位置
			int y = 0;
			// 原图的宽度
			int srcWidth = srcImage.getWidth();
			// 原图的高度
			int srcHeight = srcImage.getHeight();
			// 如果两边都小于目标边则不进行缩放
			if (srcWidth < width && srcHeight < height) {
				isThumbnail = false;
				// 如果需要补白则宽高与目标宽高一致。需要剪切
				if (fillWhite) {
					x = (width - srcWidth) / 2;
					y = (height - srcHeight) / 2;
				} else {
					// 不需要补白按原图处理
					descWidth = srcWidth;
					descHeight = srcHeight;
				}
			}
			// 如果宽度不足且高>目标高且要求截高则不进行缩放直接截高
			else if (srcWidth < width && srcHeight > height) {
				isThumbnail = false;
				// 如果不限高则按原图处理
				if (height == -1) {
					descWidth = srcWidth;
					descHeight = srcHeight;
				} else {
					// 如果需要补白
					if (fillWhite) {
						x = (width - srcWidth) / 2;
					} else {
						descWidth = srcWidth;
					}
					descHeight = height;
					y = (height - srcHeight) / 2;
				}
			}
			// 如果原图高度不足且宽>目标图且要求截宽则不进行缩放直接截宽
			else if (srcHeight < height && srcWidth > width) {
				isThumbnail = false;
				// 如果宽不限制则按原图处理
				if (width == -1) {
					descWidth = srcWidth;
					descHeight = srcHeight;
				} else {
					descWidth = width;
					// 如果需要补白
					if (fillWhite) {
						y = (height - srcHeight) / 2;
					} else {
						descHeight = srcHeight;
					}
					x = (width - srcWidth) / 2;
				}
			}
			// 原图的宽>目标图的宽且原图的高>目标图的高
			else {
				// 宽比例
				double widthScale = (double) width / srcWidth;
				// 高比例
				double heightScale = (double) height / srcImage.getHeight();
				// 原图比例
				double srcScale = (double) srcImage.getHeight()
						/ srcImage.getWidth();
				// 目标图比例
				double descScale = (double) height / width;
				// 原图的高宽比例小说明:当高缩放成一致时，宽相对较长,此时将多余的宽切掉
				if (srcScale < descScale) {
					scale = heightScale;
					// 缩放后的源图高度
					srcHeight = height;
					// 缩放后的源图宽度
					srcWidth = (int) (srcWidth * scale);
					if (width != -1) {
						x = (width - srcWidth) / 2;
					} else {
						descWidth = srcWidth;
					}
				}
				// 原图的高/宽大说明:当宽度缩放成一致时，高相对较长,此时将多余的高切掉
				else {
					scale = widthScale;
					// 缩放后的源图宽度
					srcWidth = width;
					// 缩放后的源图高度
					srcHeight = (int) (srcHeight * scale);
					if (height != -1) {
						y = (height - srcHeight) / 2;
					} else {
						descHeight = srcHeight;
					}
				}
			}
			// 图片类型
			int imageType = srcImage.getType() == BufferedImage.TYPE_CUSTOM ? BufferedImage.TYPE_INT_RGB
					: srcImage.getType();

			if (isThumbnail) {
				// 临时图片流
				BufferedImage tempImage = srcImage;
				// 缩放后的源图对象
				srcImage = new BufferedImage(srcWidth, srcHeight, imageType);
				// 缩放后的源图画板
				Graphics2D thumbnailedSrcGraphics = srcImage.createGraphics();
				thumbnailedSrcGraphics.setRenderingHint(
						RenderingHints.KEY_INTERPOLATION,
						RenderingHints.VALUE_INTERPOLATION_BICUBIC);
				// 将原图缩放并画在画板上
				thumbnailedSrcGraphics.drawRenderedImage(tempImage,
						AffineTransform.getScaleInstance(scale, scale));
				thumbnailedSrcGraphics.dispose();
			}
			// 剪切后的目标图对象
			descImage = new BufferedImage(descWidth, descHeight, imageType);
			// 剪切后的目标图画板
			Graphics2D descGraphic = descImage.createGraphics();
			// 设置目标图画板前景色
			descGraphic.setColor(Color.LIGHT_GRAY);
			// 按目标宽高添充背景
			descGraphic.fillRect(0, 0, descWidth, descHeight);
			descGraphic.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
					RenderingHints.VALUE_INTERPOLATION_BICUBIC);
			// 将源图画剪切后画在画板上
			descGraphic.drawImage(srcImage, x, y, null);
			// 如果图片宽度>300且水印图片不为null则加水印
			if (!StringUtil.isNullOrEmpty(waterImagePath)
					&& descImage.getWidth() >= 300
					&& descImage.getHeight() >= 200) {
				File waterFile = new File(waterImagePath);
				InputStream water = new FileInputStream(waterFile);
				BufferedImage waterImage = ImageIO.read(water);
				x = descWidth - waterImage.getWidth() - 15;
				y = descHeight - waterImage.getHeight() - 15;
				descGraphic.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_ATOP, 1f));
				descGraphic.drawImage(waterImage, x, y, null);
			}
			descGraphic.dispose();
			ImageIO.write(descImage, extension, descFile);
			descImage.flush();
		}
	}

	/**
	 * 图版剪切
	 * 
	 * @author zhanglizhi
	 * @date Aug 14, 2011
	 * @version 1.0
	 * @param imagePath
	 * @param subImageBounds
	 * @param subImageFilePath
	 * @throws IOException
	 */
	public static void saveSubImage(String imagePath, Rectangle subImageBounds,
			String subImageFilePath) throws IOException {
		File of = new File(imagePath);
		File subImageFile = new File(subImageFilePath);
		InputStream in = new FileInputStream(of);
		BufferedImage image = ImageIO.read(in);
		if (subImageBounds.x < 0 || subImageBounds.y < 0
				|| subImageBounds.width - subImageBounds.x > image.getWidth()
				|| subImageBounds.height - subImageBounds.y > image.getHeight()) {
			return;
		}
		BufferedImage subImage = image.getSubimage(subImageBounds.x,
				subImageBounds.y, subImageBounds.width, subImageBounds.height);
		String fileName = subImageFile.getName();
		String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);
		ImageIO.write(subImage, formatName, subImageFile);
		image.flush();
		subImage.flush();
	}

	/**
	 * 百度搜索源图
	 * 
	 * @author zhanglizhi
	 * @date 2013-2-4
	 * @version 1.0
	 * @param imageUrl
	 * @return
	 */
	public static String searchImageWithBaidu(String imageUrl, int n) {
		String result = HttpClient
				.get(String
						.format(
								"http://stu.baidu.com/i?objurl=%1$s&filename=&rt=1&rn=%2$s&ftn=indexstu&ct=1&stt=0&tn=baiduimage",
								JSUtil.encodeURIComponent(imageUrl), n));
		Matcher imageMatcher = Pattern.compile(
				"var imgdata=([\\s\\S]*?)<\\/script>", REGEX.OPTION)
				.matcher(result);
		if (imageMatcher.find()) {
			return imageMatcher.group(1);
		} else {
			return null;
		}
	}
}
